
import { jobGoto } from "../../../../job/goto";
import { jobHeal } from "../../../../job/heal";
import { jobSpread } from "../../../../job/spread";
import { GroupAttacker, getOppositeDirection } from "./offender";

export class GroupDoubleAttacker extends GroupAttacker{
    constructor(spawnRoom = undefined, targetRoomName = undefined){
        super(spawnRoom, targetRoomName);
        if(spawnRoom !== undefined){
            this.attackerName = undefined;
            this.healerName = undefined;
        }
    }
    
    serialize(){
        return {
            super: super.serialize(),
            attackerName: this.attackerName,
            healerName: this.healerName,
        };
    }

    deserialize(obj){
        super.deserialize(obj.super);
        this.attackerName = obj.attackerName;
        this.healerName = obj.healerName;
        return this;
    }
    get attacker(){
        return Game.creeps[this.attackerName];
    }
    get healer(){
        return Game.creeps[this.healerName];
    }
    set attacker(creep){
        this.attackerName = creep.name;
        return this.attacker;
    }
    set healer(creep){
        this.healerName = creep.name;
        return this.healer;
    }
    get maxSize(){
        return 2;
    }
    get creeps(){
        let ans = [];
        if(this.attacker){
            ans.push(this.attacker);
        }
        if(this.healer){
            ans.push(this.healer);
        }
        return ans;
    }
    get size(){
        let ans = 0;
        if(this.attacker){
            ans++;
        }
        if(this.healer){
            ans++;
        }
        return ans;
    }
    
    spawn(){
        if(!this.spawning){
            return ERR_FULL;
        }
        if(!this.attacker){
            return this.spawnTemplate("ranged_attacker", (creep)=>this.attacker = creep);
        }
        if(!this.healer){
            return this.spawnTemplate("healer", (creep)=>this.healer = creep);
        }
        return ERR_FULL;
    }
    clusterRun(){
        if(this.size === 0){
            return ERR_NOT_OWNER;
        }

        // healer only
        if(!this.attacker || this.targets.length === 0){
            if(this.attacker){
                jobSpread.run(this.attacker);
            }
            return jobHeal.run(this.healer, this.healer.room.find(FIND_MY_CREEPS,{
                filter(creep){
                    return creep.hits<creep.hitsMax;
                }
            }));
        }


        let attackerMoveDirection;
        let range = Infinity;
        if(this.size === this.maxSize){
            range = this.attacker.pos.getRangeTo(this.healer.pos);
        }
        if(this.size !== this.maxSize || range<=1 || range === Infinity){
            if(!this.attacker.pos.inRangeTo(this.targets[0], 4)){
                jobGoto.run(this.attacker, this.targets);
            }else{
                let avoidingRange = 3;
                let direction;
                if((this.attacker && this.attacker.hits<this.attacker.hitsMax) || (this.healer && this.healer.hits<this.healer.hitsMax)){
                    direction = getOppositeDirection(this.attacker.pos.getDirectionTo(this.targets[0]));
                }else if(!this.targets.some((hostile)=>hostile instanceof Creep && hostile.getActiveBodyparts(ATTACK) > 0 && hostile.pos.getRangeTo(this.attacker) <= avoidingRange)){
                    direction = this.attacker.pos.getDirectionTo(this.targets[0]);
                }
                let ret;
                if(direction !== undefined){
                    ret = this.move(direction, ...this.creeps);
                    if(ret === OK){
                        attackerMoveDirection = direction;
                    }
                }else{
                    ret = jobGoto.run(this.attacker, this.targets);
                }
            }
        }
        let attackerBackPos = this.step(this.attacker.pos, (getOppositeDirection(this.attacker.pos.getDirectionTo(this.targets[0]))|1)-1);
        if(this.healer !== undefined){
            let targetPos;
            if(attackerMoveDirection){
                targetPos = this.step(attackerBackPos, attackerMoveDirection);
            }
            if(!targetPos || !this.canMoveOn(targetPos)){
                targetPos = this.attacker.pos;
            }
            let distance = this.healer.pos.getRangeTo(this.attacker);
            if(distance > 7){
                this.healer.moveTo(targetPos, {reusePath:this.healer.pos.getRangeTo(targetPos)-7});
            }else if(distance > 1){
                this.healer.moveTo(targetPos);
            }else{
                if(this.healer.move(this.attacker) !== OK){
                    this.healer.moveTo(this.attacker);
                }
            }
            // if(attackerMoveDirection !== undefined || !this.healer.pos.isEqualTo(attackerBackPos)){
            //     if(this.healer.pos.inRangeTo(this.attacker, 7)){
            //         this.creepFollow(this.healer, this.attacker);
            //     }else if(!this.attacker.pos.isNearTo(this.healer.pos)){
            //         if(attackerBackPos.getRangeTo(this.healer) === Infinity){
            //             this.healer.moveTo(attackerBackPos);
            //         }else{
            //             this.healer.move(this.healer.pos.getDirectionTo(attackerMoveDirection));
            //         }
            //     }else{
            //         console.log('fdsafdsadfsa')
            //         this.healer.move(this.attacker);
            //     }
            // }

            // console.log(this.targets)
            let healTarget = this.attacker;
            if(this.attacker.hits/this.attacker.hitsMax>this.healer.hits/this.healer.hitsMax){
                healTarget = this.healer;
            }
            if(this.healer.heal(healTarget) === ERR_NOT_IN_RANGE){
                this.healer.rangedHeal(this.attacker);
            }
        }
        let ret;
        let target = jobGoto.getClosest(this.attacker, this.targets);
        if(target.pos.inRangeTo(this.attacker, 1)||this.targets.filter((target)=>target.pos.inRangeTo(this.attacker, 3)).length>=3){
            ret = this.attacker.rangedMassAttack();
        }else{
            ret = this.attacker.rangedAttack(target);
            if(ret !== OK){
                for(const target of this.targets){
                    if(this.attacker.rangedAttack(target) === OK){
                        ret = OK;
                        break;
                    }
                }
            }
        }
        console.log(this.targets);
        console.log(ret);
        return ret;
    }
}